# -*- coding: utf-8 -*-
import json
import time
import hashlib
import requests
import logging
from django.conf import settings
from common.utils import exceptions as err
from common.transaction.model import WITHDRAW_STATUS
from common.account.db.account import get_user_bankcard
from common.withdraw import check_daily_risk
from common.withdraw.db import withdraw_success_action, withdraw_failed_action
from common.utils import tz
from common.utils.types import Enum
from async import async_job


from common.utils import track_logging

_LOGGER = track_logging.getLogger(__name__)

"""
自建银行卡代理下分
"""

MCH_ID = settings.UNIONAGENCY_MCH_ID
API_KEY = settings.UNIONAGENCY_API_KEY
CHARGE_URL = settings.UNIONAGENCY_WITHDRAW_CHARGE_URL
QUERY_URL = settings.UNIONAGENCY_WITHDRAW_QUERY_URL
NOTIFY_URL = settings.UNIONAGENCY_WITHDRAW_NOTIFY_URL

WITHDRAW_ORDER_STATUS = Enum({
    "WAIT": (0L, "待下分"),
    "LOCKED": (1L, "已锁定"),
    "DONE": (2L, "已下分"),
    "REJECTED": (3L, "拒绝下分"),
})


def generate_sign(parameter, key):
    s = ''
    for k in sorted(parameter.keys()):
        s += '%s=%s&' % (k, parameter[k])
    s += 'key=%s' % key
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    sign = m.hexdigest().upper()
    return sign


def create_charge(user_id, withdraw):
    bankcard = get_user_bankcard(user_id)
    updated_info = json.loads(withdraw.extend)
    detail = updated_info.get('info', {})
    ip, city, sdk_version = detail.get('ip'), detail.get('city'), detail.get('sdk_version')
    real_price = withdraw.real_price
    trans_info = {}
    if ip and city and sdk_version:
        if bankcard:
            bank_no = bankcard.account
            bank_name = bankcard.bank
            sub_bank = bankcard.sub_bank
            real_name = bankcard.real_name
        else:
            bank_no = detail.get('no')
            bank_name = detail.get('bankname')
            real_name = detail.get('name')
            sub_bank = detail.get('bankname')
        parameter_dict = {
            'sdk_version': sdk_version,
            'mch_id': MCH_ID,
            'user_id': user_id,
            'out_trade_no': withdraw.id,
            'body': u'提现',
            'pay_type': u'bankcard',
            'pay_account_num': bank_no,
            'pay_account_username': real_name,
            'pay_account_bank': bank_name,
            'pay_account_bank_subbranch': sub_bank,
            'amount': real_price,
            'notify_url': NOTIFY_URL,
            'region': city,
            'client_ip': ip,
        }
        parameter_dict['sign'] = generate_sign(parameter_dict, API_KEY)
        _LOGGER.info('withdraw params to unionagency: %s', parameter_dict)
        res = requests.post(CHARGE_URL, data=parameter_dict, timeout=60).text
        res = json.loads(res)
        _LOGGER.info('unionagency withdraw order response: %s', res)
        if res['status'] == 2 and res['msg'] == 'out_trade_no exists':
            withdraw.status = WITHDRAW_STATUS.SUBMIT_TO_THIRD
            trans_info.update({
                'payer_no': 'union_bank_withdraw',
                'code': 'submit',
                'amount': real_price,
                'out_biz_no': withdraw.id,
                'order_id': 'miss',
                'pay_date': tz.local_now().strftime('%Y-%m-%d %H:%M:%S'),
            })
        else:
            res_dict = res.get('data', {})
            order_status = int(res_dict.get('order_status'))
            trans_info.update({
                'payer_no': 'union_bank_withdraw',
                'code': 'submit',
                'amount': real_price,
                'out_biz_no': withdraw.id,
                'order_id': res_dict.get('order_id'),
                'pay_date': tz.local_now().strftime('%Y-%m-%d %H:%M:%S'),
            })
            if order_status == 0:
                withdraw.status = WITHDRAW_STATUS.SUBMIT_TO_THIRD
            elif order_status == 3:
                withdraw.status = WITHDRAW_STATUS.FAIL
                fail_reason = res_dict.get('reason', '')
                trans_info.update({
                    'sub_msg': fail_reason,
                })
            else:
                pass
        updated_info.update({'auto_trans_info': trans_info})
        withdraw.extend = json.dumps(updated_info, ensure_ascii=False)
        withdraw.save()
        return res


def query(out_trade_no):
    parameter_dict = {
        'mch_id': MCH_ID,
        'out_trade_no': out_trade_no,
        'random_num': 4444,
    }
    parameter_dict['sign'] = generate_sign(parameter_dict, API_KEY)
    res = requests.post(QUERY_URL, data=parameter_dict, timeout=5).text
    return res


def check_notify_sign(request):
    data = request.POST.dict()
    sign = data.pop('sign')
    calculated_sign = generate_sign(data, API_KEY)
    if sign != calculated_sign:
        _LOGGER.info("unionagency sign: %s, calculated sign: %", sign, calculated_sign)
        raise err.ParamError(u'sign not pass, data: %s' % data)
    withdraw_id = data['trade_no']
    if not withdraw_id:
        _LOGGER.error(u"fatal error, out_trade_no not exists, data: %s" % data)
        raise err.ParamError('unionagency event does not contain pay ID')
    trade_status = int(data['pay_result'])
    amount = float(data['total_fee'])
    trade_no = data['trade_no']
    _LOGGER.info(u'unionagency check_notify, data %s', data)
    if trade_status == WITHDRAW_ORDER_STATUS.DONE:
        succ = withdraw_success_action(withdraw_id, amount, trade_no, payer_no='union_bank_withdraw')
        if succ:
            _LOGGER.info('Auto trans bankcard, check_bankcard_withdraw_notify_sign succ')
            check_daily_risk(float(amount))
    elif trade_status == WITHDRAW_ORDER_STATUS.REJECTED:
        reason = data.get('reason', '')
        withdraw_failed_action(withdraw_id, amount, trade_status,
                               trade_status, reason, trade_no, payer_no='union_bank_withdraw')
        async_job.stats_withdraw.delay(withdraw_id)
    else:
        raise err.ParamError(u'Wrong trade status: %s', trade_status)
